禁用控制器结果的包装
Disable Wrapping of Controller Results
我目前使用的是 Abp.AspNetCore 的 v3.2.5。
我正在尝试将 Microsoft.AspNetCore.OData 的 Alpha 包集成到目前看起来还不错的项目中。
然而,当我尝试查询元数据控制器时 http://localhost:51078/odata/v1/$metadata 结果被包装了。
现在这也是 ODataController 的问题,但我可以简单地添加
[DontWrapResult] 属性。
我没有直接访问 MetadataController 的权限,所以我无法添加该属性。无论如何要禁用 Abp 项目的包装?
谢谢
编辑
这是当前的 ConfigureServices 方法
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
services
.AddAuthentication()
.AddCsDeviceAuth(options => { });
services
.AddOData();
//Configure Abp and Dependency Injection
var provider = services.AddAbp<PortalWebODataModule>(options =>
{
//Configure Log4Net logging
options.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.LogUsing<Log4NetLoggerFactory>().WithConfig("log4net.config")
);
});
services.Configure<MvcOptions>(options =>
{
var abpResultFilter = options.Filters.First(f => f is AbpResultFilter);
options.Filters.Remove(abpResultFilter);
options.Filters.AddService(typeof(ODataResultFilter));
});
return provider;
}
您可以实施 IResultFilter
并将 WrapOnSuccess
设置为 false:
public class ResultFilter : IResultFilter, ITransientDependency
{
private readonly IAbpAspNetCoreConfiguration _configuration;
public ResultFilter(IAbpAspNetCoreConfiguration configuration)
{
_configuration = configuration;
}
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.HttpContext.Request.Path.Value.Contains("odata"))
{
var methodInfo = context.ActionDescriptor.GetMethodInfo();
var wrapResultAttribute =
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(
methodInfo,
_configuration.DefaultWrapResultAttribute
);
wrapResultAttribute.WrapOnSuccess = false;
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
// No action
}
private TAttribute GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<TAttribute>(MemberInfo memberInfo, TAttribute defaultValue = default(TAttribute), bool inherit = true)
where TAttribute : class
{
return memberInfo.GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? memberInfo.DeclaringType?.GetTypeInfo().GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? defaultValue;
}
}
然后,在Startup
class中,在ConfigureServices
方法中添加过滤器:
services.AddMvc(options =>
{
options.Filters.AddService(typeof(ResultFilter));
});
参考文献:
备选方案;完全禁用系统内的 WrapResult 行为(在核心模块注册时):
var abpAspNetCoreConfiguration = Configuration.Modules.AbpAspNetCore();
abpAspNetCoreConfiguration.DefaultWrapResultAttribute.WrapOnSuccess = false;
abpAspNetCoreConfiguration.DefaultWrapResultAttribute.WrapOnError = false;
abpAspNetCoreConfiguration
.CreateControllersForAppServices(
typeof(AccessApplicationModule).GetAssembly()
);
WrapOnSuccess 和 WrapOnError 标志可以设置为假值。
ABP v6.5 及更高版本
实现IWrapResultFilter
并将其添加到模块的PreInitialize
方法中的WrapResultFilters
。
有关详细信息,请参阅
ABP v6.5 之前
...包括题中提到的ABP v3.2.5
子类 AbpResultFilter
:
using Abp.AspNetCore.Configuration;
using Abp.AspNetCore.Mvc.Results;
using Abp.AspNetCore.Mvc.Results.Wrapping;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace AbpODataDemo.Web.Host.Filters
{
public class ODataResultFilter : AbpResultFilter
{
public ODataResultFilter(IAbpAspNetCoreConfiguration configuration, IAbpActionResultWrapperFactory actionResultWrapperFactory)
: base(configuration, actionResultWrapperFactory)
{
}
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.HttpContext.Request.Path.Value.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
base.OnResultExecuting(context);
}
}
}
在Startup
ConfigureServices
方法中将AbpResultFilter
替换为:
services.PostConfigure<MvcOptions>(options =>
{
var index = options.Filters.IndexOf(new ServiceFilterAttribute(typeof(AbpResultFilter)));
if (index != -1)
{
options.Filters.RemoveAt(index);
options.Filters.Insert(index, new ServiceFilterAttribute(typeof(ODataResultFilter)));
}
});
参考:https://github.com/aspnetboilerplate/sample-odata/pull/16
我目前使用的是 Abp.AspNetCore 的 v3.2.5。
我正在尝试将 Microsoft.AspNetCore.OData 的 Alpha 包集成到目前看起来还不错的项目中。
然而,当我尝试查询元数据控制器时 http://localhost:51078/odata/v1/$metadata 结果被包装了。 现在这也是 ODataController 的问题,但我可以简单地添加 [DontWrapResult] 属性。
我没有直接访问 MetadataController 的权限,所以我无法添加该属性。无论如何要禁用 Abp 项目的包装?
谢谢
编辑
这是当前的 ConfigureServices 方法
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
services
.AddAuthentication()
.AddCsDeviceAuth(options => { });
services
.AddOData();
//Configure Abp and Dependency Injection
var provider = services.AddAbp<PortalWebODataModule>(options =>
{
//Configure Log4Net logging
options.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.LogUsing<Log4NetLoggerFactory>().WithConfig("log4net.config")
);
});
services.Configure<MvcOptions>(options =>
{
var abpResultFilter = options.Filters.First(f => f is AbpResultFilter);
options.Filters.Remove(abpResultFilter);
options.Filters.AddService(typeof(ODataResultFilter));
});
return provider;
}
您可以实施 IResultFilter
并将 WrapOnSuccess
设置为 false:
public class ResultFilter : IResultFilter, ITransientDependency
{
private readonly IAbpAspNetCoreConfiguration _configuration;
public ResultFilter(IAbpAspNetCoreConfiguration configuration)
{
_configuration = configuration;
}
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.HttpContext.Request.Path.Value.Contains("odata"))
{
var methodInfo = context.ActionDescriptor.GetMethodInfo();
var wrapResultAttribute =
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(
methodInfo,
_configuration.DefaultWrapResultAttribute
);
wrapResultAttribute.WrapOnSuccess = false;
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
// No action
}
private TAttribute GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<TAttribute>(MemberInfo memberInfo, TAttribute defaultValue = default(TAttribute), bool inherit = true)
where TAttribute : class
{
return memberInfo.GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? memberInfo.DeclaringType?.GetTypeInfo().GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? defaultValue;
}
}
然后,在Startup
class中,在ConfigureServices
方法中添加过滤器:
services.AddMvc(options =>
{
options.Filters.AddService(typeof(ResultFilter));
});
参考文献:
备选方案;完全禁用系统内的 WrapResult 行为(在核心模块注册时):
var abpAspNetCoreConfiguration = Configuration.Modules.AbpAspNetCore();
abpAspNetCoreConfiguration.DefaultWrapResultAttribute.WrapOnSuccess = false;
abpAspNetCoreConfiguration.DefaultWrapResultAttribute.WrapOnError = false;
abpAspNetCoreConfiguration
.CreateControllersForAppServices(
typeof(AccessApplicationModule).GetAssembly()
);
WrapOnSuccess 和 WrapOnError 标志可以设置为假值。
ABP v6.5 及更高版本
实现IWrapResultFilter
并将其添加到模块的PreInitialize
方法中的WrapResultFilters
。
有关详细信息,请参阅 ...包括题中提到的ABP v3.2.5 子类 在 参考:https://github.com/aspnetboilerplate/sample-odata/pull/16ABP v6.5 之前
AbpResultFilter
:using Abp.AspNetCore.Configuration;
using Abp.AspNetCore.Mvc.Results;
using Abp.AspNetCore.Mvc.Results.Wrapping;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace AbpODataDemo.Web.Host.Filters
{
public class ODataResultFilter : AbpResultFilter
{
public ODataResultFilter(IAbpAspNetCoreConfiguration configuration, IAbpActionResultWrapperFactory actionResultWrapperFactory)
: base(configuration, actionResultWrapperFactory)
{
}
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.HttpContext.Request.Path.Value.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
base.OnResultExecuting(context);
}
}
}
Startup
ConfigureServices
方法中将AbpResultFilter
替换为:services.PostConfigure<MvcOptions>(options =>
{
var index = options.Filters.IndexOf(new ServiceFilterAttribute(typeof(AbpResultFilter)));
if (index != -1)
{
options.Filters.RemoveAt(index);
options.Filters.Insert(index, new ServiceFilterAttribute(typeof(ODataResultFilter)));
}
});